package generics;

/**
 *  ？和 T 的区别
 *
 *
 * ？和 T 都表示不确定的类型，区别在于我们可以对 T 进行操作，但是对 ？不行，比如如下这种 ：
 *
 * // 可以
 * T t = operate();
 *
 * // 不可以
 * ？car = operate();
 *
 * 简单总结下：
 *
 * T 是一个 确定的 类型，通常用于泛型类和泛型方法的定义，
 * ？是一个 不确定 的类型，通常用于泛型方法的调用代码和形参，不能用于定义类和泛型方法。
 *
 * 区别1：通过 T 来 确保 泛型参数的一致性
 * // 通过 T 来 确保 泛型参数的一致性
 * public <T extends Number> void
 * test(List<T> dest, List<T> src)
 *
 * //通配符是 不确定的，所以这个方法不能保证两个 List 具有相同的元素类型
 * public void
 * test(List<? extends Number> dest, List<? extends Number> src)
 *
 * 像下面的代码中，约定的 T 是 Number 的子类才可以，但是申明时是用的 String ，所以就会飘红报错。
 *
 * 不能保证两个 List 具有相同的元素类型的情况
 *
 * GlmapperGeneric<String> glmapperGeneric = new GlmapperGeneric<>();
 * List<String> dest = new ArrayList<>();
 * List<Number> src = new ArrayList<>();
 * glmapperGeneric.testNon(dest,src);
 *
 * 上面的代码在编译器并不会报错，但是当进入到 testNon 方法内部操作时（比如赋值），对于 dest 和 src 而言，就还是需要进行类型转换。
 *
 * 区别2：类型参数可以多重限定而通配符不行
 * 图片
 * 使用 & 符号设定多重边界（Multi Bounds)，指定泛型类型 T 必须是 MultiLimitInterfaceA 和 MultiLimitInterfaceB 的共有子类型，此时变量 t 就具有了所有限定的方法和属性。对于通配符来说，因为它不是一个确定的类型，所以不能进行多重限定。
 *
 * 区别3：通配符可以使用超类限定而类型参数不行
 * 类型参数 T 只具有 一种 类型限定方式：
 *
 * T extends A
 *
 * 但是通配符 ? 可以进行 两种限定：
 *
 * ? extends A
 * ? super A
 *
 * Class<T>和 Class<?>区别
 * 前面介绍了 ？和 T 的区别，那么对于，Class<T>和 <Class<?>又有什么区别呢？Class<T>和 Class<?>
 *
 * 最常见的是在反射场景下的使用，这里以用一段发射的代码来说明下。
 *
 * // 通过反射的方式生成  multiLimit
 * // 对象，这里比较明显的是，我们需要使用强制类型转换
 * MultiLimit multiLimit = (MultiLimit)
 * Class.forName("com.glmapper.bridge.boot.generic.MultiLimit").newInstance();
 *
 * 对于上述代码，在运行期，如果反射的类型不是 MultiLimit 类，那么一定会报 java.lang.ClassCastException 错误。
 *
 * 对于这种情况，则可以使用下面的代码来代替，使得在在编译期就能直接 检查到类型的问题：
 *
 * Class<T>在实例化的时候，T 要替换成具体类。Class<?>它是个通配泛型，? 可以代表任何类型，所以主要用于声明时的限制情况。比如，我们可以这样做申明：
 *
 * // 可以
 * public Class<?> clazz;
 * // 不可以，因为 T 需要指定类型
 * public Class<T> clazzT;
 *
 * 所以当不知道定声明什么类型的 Class 的时候可以定义一 个Class<?>。
 *
 *
 * 那如果也想 public Class<T> clazzT;这样的话，就必须让当前的类也指定 T ，
 *
 * public class Test3<T> {
 *     public Class<?> clazz;
 *     // 不会报错
 *     public Class<T> clazzT;
 *
 *
 *
 * */
public class Lesson4 {

}
